﻿//--------------------------------------------------
// Author: 张羽乔
// License: LGPL 3
//--------------------------------------------------

#ifndef PT_MATH_MATH_H
#define PT_MATH_MATH_H

#if defined(PTWIN32)
#define PT_VECTORCALL __vectorcall
#elif defined(PTPOSIX)
#if defined(PTX86) || defined(PTX64)
#define PT_VECTORCALL __attribute__((vectorcall))
#elif  defined(PTARM) || defined(PTARM64)
#define PT_VECTORCALL
#else
#error 未知的平台
#endif
#else
#error 未知的平台
#endif

//线性代数
struct PTVector2F
{
	float x;
	float y;
};

struct PTVector3F
{
	float x;
	float y;
	float z;
};

struct PTVector4F
{
	float x;
	float y; 
	float z;
	float w;
};

struct PTDualQuaternionF
{
	float _0[4];
	float _1[4];
};

struct PTMatrix4x4F
{
	PTVector4F r[4];
};

struct PTVectorSIMD;//列向量
struct PTQuaternionSIMD;//四元数
struct PTDualQuaternionSIMD;//对偶四元数
struct PTMatrixSIMD;//作用于列向量行序为主序(内存布局等价于作用于行向量列序为主序)

inline PTVectorSIMD PT_VECTORCALL PTVector3FLoad(const PTVector3F *pSource);//x y z _

inline PTVectorSIMD PT_VECTORCALL PTVector3FLoadA(const PTVector3F *pSource);//x y z _

inline void PT_VECTORCALL PTVector3FStore(PTVector3F* pDestination, PTVectorSIMD V);

inline void PT_VECTORCALL PTVector3FStoreA(PTVector3F* pDestination, PTVectorSIMD V);

inline PTVectorSIMD PT_VECTORCALL PTVector3SIMDDot(PTVectorSIMD V1, PTVectorSIMD V2);

inline PTVectorSIMD PT_VECTORCALL PTVector3SIMDCross(PTVectorSIMD V1, PTVectorSIMD V2);

inline PTVectorSIMD PT_VECTORCALL PTVector3SIMDNormalize(PTVectorSIMD V);

inline PTVectorSIMD PT_VECTORCALL PTVector3SIMDTransform(PTMatrixSIMD M, PTVectorSIMD V);

inline PTVectorSIMD PT_VECTORCALL PTVector4FLoad(const PTVector4F *pSource);//x y z w

inline PTVectorSIMD PT_VECTORCALL PTVector4FLoadA(const PTVector4F *pSource);//x y z w

inline void PT_VECTORCALL PTVector4FStore(PTVector4F* pDestination, PTVectorSIMD V);

inline void PT_VECTORCALL PTVector4FStoreA(PTVector4F* pDestination, PTVectorSIMD V);

inline PTVectorSIMD PT_VECTORCALL PTVector4SIMDDot(PTVectorSIMD V1, PTVectorSIMD V2);

inline PTVectorSIMD PT_VECTORCALL PTVector4SIMDTransform(PTMatrixSIMD M, PTVectorSIMD V);

inline PTVectorSIMD PT_VECTORCALL PTVectorSIMDNegate(PTVectorSIMD V);

inline PTQuaternionSIMD PT_VECTORCALL PTQuaternionSIMDRotationAxis(PTVectorSIMD Axis, float Angle);

inline PTQuaternionSIMD PT_VECTORCALL PTQuaternionSIMDRotationNormalAxis(PTVectorSIMD NormalAxis, float Angle);

inline PTDualQuaternionSIMD PT_VECTORCALL PTQuaternionRigidMatrix(PTMatrixSIMD M);

inline void PT_VECTORCALL PTMatrix4x4FStore(PTMatrix4x4F* pDestination, PTMatrixSIMD M);

inline void PT_VECTORCALL PTMatrix4x4FStoreA(PTMatrix4x4F* pDestination, PTMatrixSIMD M);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDTranspose(PTMatrixSIMD M);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDTranslation(float OffsetX, float OffsetY, float OffsetZ);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDRotationQuaternion(PTQuaternionSIMD Q);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDLookToRH(PTVectorSIMD EyePosition, PTVectorSIMD EyeDirection, PTVectorSIMD UpDirection, PTMatrixSIMD *pInverse = NULL);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDPerspectiveFovRH(float FovAngleY, float AspectHByW, float NearZ, float FarZ, PTMatrixSIMD *pInverse = NULL);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDPerspectiveRH(float ViewWidth, float ViewHeight, float NearZ, float FarZ, PTMatrixSIMD *pInverse = NULL);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDOrthographicRH(float ViewWidth, float ViewHeight, float NearZ, float FarZ);

inline PTMatrixSIMD PT_VECTORCALL PTMatrix4x4SIMDMultiply(PTMatrixSIMD M1, PTMatrixSIMD M2);


//相交测试

enum PTIntersectionType
{
	PTDISJOINT = 0,//互斥
	PTINTERSECT = 1,//相交
	PTCONTAIN = 2,//包含
};

struct PTFrustumF
{
	PTVector4F Plane[6];
};

struct PTFrustumSIMD;
struct PTSphereSIMD;
struct PTAABSIMD;
struct PTOBSIMD;

inline PTFrustumSIMD PT_VECTORCALL PTFrustumSIMDLoadRH(PTMatrixSIMD ViewProjection);

inline void PT_VECTORCALL PTFrustumFStore(PTFrustumF *pDestination, PTFrustumSIMD F);

inline void PT_VECTORCALL PTFrustumFStoreA(PTFrustumF *pDestination, PTFrustumSIMD F);

inline PTSphereSIMD PT_VECTORCALL PTSphereSIMDLoad(PTVector3F *pCenter,float Radius);

inline PTAABSIMD PT_VECTORCALL PTAABSIMDLoad(PTVector3F *pMin, PTVector3F *pMax);

//inline PTSIMDOB PT_VECTORCALL PTSIMDOBLoad(PTV3F *pCenter, PTV3F *pHalfDiagonal, PTSIMDMatrix Rotation);
//inline PTSIMDOB PT_VECTORCALL PTSIMDOBLoad(PTV3F *pCenter, PTV3F *pHalfDiagonal, PTV3F *pRotationXYZ);

inline PTIntersectionType PT_VECTORCALL PTFrustumSIMDSphereSIMDIntersect(PTFrustumSIMD F, PTSphereSIMD S);

inline PTIntersectionType PT_VECTORCALL PTFrustumSIMDAABSIMDIntersect(PTFrustumSIMD F, PTAABSIMD AAB);

//inline PTIntersectionType PT_VECTORCALL PTFrustumSIMDOBSIMDIntersect(PTSIMDFrustum F, PTSIMDOB OB);

#if defined(PTX86) || defined(PTX64)
#include <xmmintrin.h>
#include <emmintrin.h>
#include "SSE/PTMathSIMD.inl"
#elif defined(PTARM) || defined(PTARM64)
#include <arm_neon.h>
#include "NEON/PTMathSIMD.inl"
#else
#error 未知的架构
#endif

#endif